import React, { Component } from 'react'
import { connect } from 'react-redux'
import { PaddingContainer } from 'components/containers'
import { ValidType } from 'components/validForm'
import { validForm as validFormDuck } from 'ducks'
import AddClass from 'graphql/project/config/addClass.graphql'
import GetTags from 'graphql/project/config/getAllTags.graphql'
import ValidClassName from 'graphql/project/config/validClassName.graphql'
import {
  Form as FormTable,
  Section as TableSection,
  Input,
  Switch,
  Submit,
  ColorInput,
  MultiSwitch,
} from 'components/tableForm'
import {
  Grid, Table, Header, Label, Input as UiInput, Dropdown,
} from 'semantic-ui-react'
import { TableRow, OptionIcon } from 'components/memberTable'
import {
  Stage, Layer, Circle, Line,
} from 'react-konva'
import { BasicButton } from 'components/Button'
import InputColor from 'components/colorInput'

const CANVAS_WIDTH_PADDING = 420
const CANVAS_WIDTH = 400
const PADDING = 10

const getAccodinate = a => a * CANVAS_WIDTH + PADDING

const getVariables = settings => (values) => {
  const result = { setting: {} }
  if (values.name) result.name = values.name.value
  if (values.description) result.description = values.description.value
  if (values.color) result.color = values.color.value
  if (values.tagType) result.classType = values.tagType.value
  if (values.tagType && values.tagType.value === 'keypoint') result.setting = settings
  if (values.tags) {
    result.setting.tags = Object.keys(values.tags.value).reduce((pre, next) => {
      if (values.tags.value[next]) pre.push(next)
      return pre
    }, [])
  }
  return result
}

const descriptionRule = [
  {
    type: ValidType.REGULAR,
    value: /^.{1,500}$/,
    errorMessage: '标签名称不能为空',
  },
]

const pts = {}

const lns = []

class AddTagConfig extends Component {
  state = {
    points: pts,
    lines: lns,
    addPoint: { color: '#000000', nullable: false },
    addLine: {},
  }

  actionMovePoint = name => ({ target }) => {
    this.setState((preState) => {
      const oldPoints = preState.points
      let newX = (target.attrs.x - PADDING) / CANVAS_WIDTH
      let newY = (target.attrs.y - PADDING) / CANVAS_WIDTH
      newX = newX < 0 ? 0 : newX
      newX = newX > 1 ? 1 : newX
      newY = newY < 0 ? 0 : newY
      newY = newY > 1 ? 1 : newY
      oldPoints[name].x = newX
      oldPoints[name].y = newY

      return { points: Object.assign({}, preState.points, oldPoints) }
    })
  }

  changePointName = (d, { value }) => this.setState(preState => ({ addPoint: Object.assign({}, preState.addPoint, { name: value }) }))

  changeColor = color => this.setState(preState => ({ addPoint: Object.assign({}, preState.addPoint, { color }) }))

  changeNullable = (d, { value }) => {
    console.log('changeNullable', value)
    this.setState(preState => ({
      addPoint: Object.assign({}, preState.addPoint, { nullable: value === 'true' }),
    }))
  }

  actionAddPoint = () => {
    const { points, addPoint } = this.state
    points[addPoint.name] = {
      x: Math.random(),
      y: Math.random(),
      color: addPoint.color,
      nullable: addPoint.nullable,
    }
    this.setState({ points })
  }

  canAddPoint = () => {
    const { addPoint } = this.state
    return addPoint.color && addPoint.name && addPoint.name !== ''
  }

  changeLineStart = (d, { value }) => this.setState(preState => ({ addLine: Object.assign({}, preState.addLine, { start: value }) }))

  changeLineEnd = (d, { value }) => this.setState(preState => ({ addLine: Object.assign({}, preState.addLine, { end: value }) }))

  canAddLine = () => {
    const { addLine } = this.state
    return (
      addLine.start
      && addLine.end
      && addLine.start !== ''
      && addLine.end !== ''
      && addLine.start !== addLine.end
    )
  }

  actionAddLine = () => {
    const { addLine } = this.state
    this.setState(preState => ({ lines: [...preState.lines, [addLine.start, addLine.end]] }))
  }

  componentDidMount = () => {}

  render() {
    const {
      points, lines, addPoint, addLine,
    } = this.state
    const { values, project } = this.props
    const { projectId } = project
    const returnUrl = `/project/${project.orgName}/${project.projectName}/config/class`
    const tagTypeField = values ? values.tagType : undefined
    const tagType = tagTypeField ? tagTypeField.value : undefined
    const nameRule = [
      {
        type: ValidType.REGULAR,
        value: /^[\s\S]*.*[^\s][\s\S]*$/,
        errorMessage: '标签名称不能为空',
      },
      {
        type: ValidType.REMOTE,
        value: {
          query: ValidClassName,
          params: { projectId },
        },
        errorMessage: '该标注类别已经存在于当前项目',
        getResult: re => re.project_class.length === 0,
      },
    ]

    return (
      <FormTable>
        <TableSection header="添加标签">
          <Input
            name="name"
            header="类别名称"
            description="类别名称由 1 ~ 63 个字符组成 ，可包含 字母、数字、中划线。"
            rules={nameRule}
          />
          <Input
            name="description"
            header="类别描述"
            description="类别描述不能大于500个字符（不能为空）"
            rules={descriptionRule}
            textArea
          />
          <ColorInput name="color" header="标注颜色" description="用于绘制标注与展示的颜色" />
          <MultiSwitch
            name="tags"
            header="类别标签"
            description="可以为类别添加多个标签"
            query={{
              query: GetTags,
              variables: { projectId },
              getData: (data) => {
                if (!data && !data.tag) return []
                return data.tag.map(tag => ({ name: tag.id, value: tag.name }))
              },
            }}
          />
          <Switch
            name="tagType"
            header="标注类型"
            description="选择标注类型"
            options={[
              { name: 'rectangle', value: '矩形标注' },
              { name: 'polygon', value: '多边形标注' },
              { name: 'keypoint', value: '关键点标注' },
            ]}
          />
        </TableSection>
        {tagType === 'keypoint' && (
          <Grid columns={1} divided>
            <Grid.Row>
              <Grid.Column>
                <Header as="h3" dividing>
                  关键点
                </Header>
                <Table basic="very">
                  <Table.Header>
                    <Table.Row>
                      <Table.HeaderCell
                        style={{
                          wordBreak: 'keep-all',
                          whiteSpace: 'nowrap',
                        }}
                      >
                        名称
                      </Table.HeaderCell>
                      <Table.HeaderCell>颜色</Table.HeaderCell>
                      <Table.HeaderCell />
                    </Table.Row>
                  </Table.Header>
                  <Table.Body>
                    {points
                      && Object.keys(points).map(point => (
                        <TableRow>
                          <Table.Cell collapsing>{point}</Table.Cell>
                          <Table.Cell>
                            <Label
                              circular
                              style={{ backgroundColor: points[point].color }}
                              size="mini"
                            />
                          </Table.Cell>
                          <Table.Cell collapsing="right">
                            <OptionIcon className="options" color="red" name="remove" />
                          </Table.Cell>
                        </TableRow>
                      ))}
                    <TableRow>
                      <Table.Cell collapsing>
                        <UiInput onChange={this.changePointName} placeholder="节点名称..." />
                      </Table.Cell>
                      <Table.Cell>
                        <InputColor color={addPoint.color} onChange={this.changeColor} />
                      </Table.Cell>
                      <Table.Cell collapsing="right">
                        <BasicButton disabled={!this.canAddPoint()} onClick={this.actionAddPoint}>
                          添加节点
                        </BasicButton>
                      </Table.Cell>
                    </TableRow>
                  </Table.Body>
                </Table>
              </Grid.Column>
            </Grid.Row>
            <Grid.Row>
              <Grid.Column>
                <Header as="h3" dividing>
                  连接线
                </Header>
                <Table basic="very">
                  <Table.Header>
                    <Table.Row>
                      <Table.HeaderCell
                        style={{
                          wordBreak: 'keep-all',
                          whiteSpace: 'nowrap',
                        }}
                      >
                        连线起点
                      </Table.HeaderCell>
                      <Table.HeaderCell>连线终点</Table.HeaderCell>
                      <Table.HeaderCell />
                    </Table.Row>
                  </Table.Header>
                  <Table.Body>
                    {lines
                      && lines.map(line => (
                        <TableRow>
                          <Table.Cell collapsing>{line[0]}</Table.Cell>
                          <Table.Cell>{line[1]}</Table.Cell>
                          <Table.Cell collapsing="right">
                            <OptionIcon className="options" color="blue" name="pencil alternate" />
                            <OptionIcon className="options" color="red" name="remove" />
                          </Table.Cell>
                        </TableRow>
                      ))}
                    <TableRow>
                      <Table.Cell collapsing>
                        <Dropdown
                          options={Object.keys(points).map(key => ({
                            key,
                            value: key,
                            text: key,
                          }))}
                          selection
                          onChange={this.changeLineStart}
                        />
                      </Table.Cell>
                      <Table.Cell>
                        <Dropdown
                          options={Object.keys(points).map(key => ({
                            key,
                            value: key,
                            text: key,
                          }))}
                          selection
                          onChange={this.changeLineEnd}
                        />
                      </Table.Cell>
                      <Table.Cell collapsing="right">
                        <BasicButton disabled={!this.canAddLine()} onClick={this.actionAddLine}>
                          添加连线
                        </BasicButton>
                      </Table.Cell>
                    </TableRow>
                  </Table.Body>
                </Table>
              </Grid.Column>
            </Grid.Row>
            <Grid.Row>
              <Grid.Column>
                <Stage width={CANVAS_WIDTH_PADDING} height={CANVAS_WIDTH_PADDING}>
                  <Layer>
                    {lines
                      && lines.map(line => (
                        <Line
                          points={[
                            getAccodinate(points[line[0]].x),
                            getAccodinate(points[line[0]].y),
                            getAccodinate(points[line[1]].x),
                            getAccodinate(points[line[1]].y),
                          ]}
                          stroke="black"
                        />
                      ))}
                    {points
                      && Object.keys(points).map(key => (
                        <Circle
                          draggable
                          x={points[key].x * CANVAS_WIDTH + 10}
                          y={points[key].y * CANVAS_WIDTH + 10}
                          radius={10}
                          fill={points[key].color}
                          onDragEnd={this.actionMovePoint(key)}
                        />
                      ))}
                  </Layer>
                </Stage>
              </Grid.Column>
            </Grid.Row>
          </Grid>
        )}
        <Submit
          submit={{
            text: '提交',
            variables: { projectId },
            getVariables: getVariables({ points, lines }),
            mutation: AddClass,
            success: () => returnUrl,
          }}
          cancle={{ text: '取消', url: returnUrl }}
          redirect
        />
      </FormTable>
    )
  }
}

const mapStateToProps = state => ({
  values: validFormDuck.selectors.values(state),
})

export default connect(
  mapStateToProps,
  null,
)(AddTagConfig)
